package org.gpf.game.tank.online;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
/**
 * 网络客户端
 * @author gaopengfei
 * @date 2015-4-21 下午5:35:51
 */
public class NetClient {

	private int udpPort ; 		// 客户端的udp端口
	TankClient tc;
	DatagramSocket ds = null;
	
	String serverIP; 			// 服务器IP
	
	/**
	 * 取得UDP端口（客户端接收数据用）
	 * @return UDP端口
	 */
	public int getUdpPort() {
		return udpPort;
	}

	/**
	 * 设定UDP端口（客户端接收数据用）
	 * @param udpPort UDP端口
	 */
	public void setUdpPort(int udpPort) {
		this.udpPort = udpPort;
	}

	/**
	 * 根据场所构建网络客户端
	 * @param tc 场所
	 */
	public NetClient(TankClient tc) {
		this.tc = tc;
	}
	
	/**
	 * 连接服务器
	 * @param IP 服务器IP
	 * @param port 服务器端口
	 */
	public void connect(String IP,int port){
		
		this.serverIP = IP;
		try {
			ds = new DatagramSocket(udpPort);
		} catch (SocketException e) {
			e.printStackTrace();
		}
		
		Socket s = null;
		try {
			s = new Socket(IP, port);
			DataOutputStream dos = new DataOutputStream(s.getOutputStream());
			dos.writeInt(udpPort); // 向服务器发送自己的UDP端口号
			DataInputStream dis = new DataInputStream(s.getInputStream());
			int id = dis.readInt(); // 取回服务器分配给客户端的唯一的id
			tc.myTank.id = id;
			if (id%2==0) {
				tc.myTank.good = false; // 反方
			}else {
				tc.myTank.good = true; // 正方
			}
			System.out.println("成功连接到服务器，服务器给我分配的id是：" + id);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if (s!=null) {
				try {
					s.close();
					s = null;
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		
		TankNewMsg msg = new TankNewMsg(tc.myTank); // 主战坦克
		send(msg);
		
		new Thread(new UDPRecvThread()).start();
	}
	
	/**
	 * 向服务器发送自己的信息
	 * @param msg 待发送的消息
	 */
	public void send(Msg msg){
		
		msg.send(ds,serverIP,TankServer.UDP_PORT);
	}
	
	/**
	 * 接受服务器发送给自己其他网络的数据报
	 * @author gaopengfei
	 * @date 2015-4-22 下午9:57:33
	 */
	private class UDPRecvThread implements Runnable{

		byte[] buf = new byte[1024];
		
		@Override
		public void run() {
			
			while (ds!=null) {
				DatagramPacket dp = new DatagramPacket(buf, buf.length);
				try {
					ds.receive(dp);	// 在拿到数据报之前一直阻塞
					System.out.println("客户端收到了服务器发送的数据报，该数据包中有其他坦克的信息。");
					// 对数据报进行解析
					parse(dp);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		/**
		 * 对收到的数据报进行解析
		 * @param dp
		 * @throws IOException 
		 */
		private void parse(DatagramPacket dp) throws IOException {

			ByteArrayInputStream bais = new ByteArrayInputStream(buf,0,dp.getLength());
			DataInputStream dis = new DataInputStream(bais);
			int msgType = dis.readInt();
			Msg msg = null;
			switch (msgType) {
			case Msg.TANK_NEW_MSG:
				msg = new TankNewMsg(NetClient.this.tc); // 在一个内部类中去访问封装类的对象
				msg.parse(dis);
				break;
			case Msg.TANK_MOVE_MSG:
				msg = new TankMoveMessage(NetClient.this.tc);
				msg.parse(dis);
				break;
			case Msg.MISSILE_NEW_MSG:
				msg = new MissileNewMessage(NetClient.this.tc);
				msg.parse(dis);
				break;
			case Msg.TANK_DEAD_MSG:
				msg = new TankDeadMsg(NetClient.this.tc);
				msg.parse(dis);
				break;
			case Msg.MISSILE_DEAD_MSG:
				msg = new MissileDeadMsg(NetClient.this.tc);
				msg.parse(dis);
				break;
			default:
				break;
			}
			
		}
		
	}
}
